# -*- coding: utf-8 -*-
# Created by liangfuting on 2020/6/22
# Copyright (c) 2020 liangfuting. All rights reserved.
from collections import OrderedDict
from django.shortcuts import render,HttpResponse,redirect,reverse,get_object_or_404,get_list_or_404
from rbac.models import Menu,Permission,Role,UserInfo
from rbac.forms.permission import PermissionModelForm,MultiAddPermissionForm,MultiEditPermissionForm
from django.http import QueryDict
from django.conf import settings
from django.utils.module_loading import import_string
from django.forms import formset_factory
from rbac.service.urls import memory_reverse_url
from rbac.service.routes import get_all_url_dict

def permission_add(request,second_menu_id):
    # 增加一个保留原搜索条件的功能，在添加完新菜单后，能回到原来的激活的菜单中
    # print("second_menu_id:",second_menu_id)
    second_menu_object = get_object_or_404(Permission,pk=second_menu_id)
    # print(second_menu_object)
    form = PermissionModelForm()
    if request.method == "POST":
        form = PermissionModelForm(data=request.POST)
        if form.is_valid():
            # form.instance=Permission(title='',url='',name='',pid='')
            form.instance.pid=second_menu_object
            form.save()
            return redirect(memory_reverse_url(request, 'rbac:menu_list'))
    context = {
        'form': form,
    }
    return render(request, 'rbac/change.html', context)


def permission_edit(request,pk):
    permission_object=Permission.objects.filter(pk=pk).first()
    # second_menu_object=permission_object.parents
    # print(second_menu_object)
    form = PermissionModelForm(instance=permission_object)
    if request.method == "POST":
        form = PermissionModelForm(data=request.POST,instance=permission_object)
        if form.is_valid():
            form.save()
            return redirect(memory_reverse_url(request, 'rbac:menu_list'))
    context = {
        'form': form,
    }
    return render(request, 'rbac/change.html', context)


def permission_del(request,pk):
    origin_url = memory_reverse_url(request, 'rbac:menu_list')
    if request.method == "GET":
        return render(request, 'rbac/delete.html', {'cancel': origin_url})
    Permission.objects.filter(pk=pk).delete()
    return redirect(origin_url)


def multi_permissions(request):
    """
    获取项目中所有的url
    :param request:
    :return:
    """
    post_type=request.GET.get("type")
    # print(request.GET.get("type"))
    generate_formset_class=formset_factory(MultiAddPermissionForm,extra=0)
    update_formset_class=formset_factory(MultiEditPermissionForm,extra=0)
    generate_formset=None
    update_formset=None
    #批量添加
    if request.method=="POST" and post_type=="generate":
        formset=generate_formset_class(data=request.POST)
        if formset.is_valid():
            object_list=[]
            post_row_list=formset.cleaned_data
            has_error=False
            for i in range(0,formset.total_form_count()):
                row_dict=post_row_list[i]
                try:
                    new_object=Permission(**row_dict)
                    new_object.validate_unique()#唯一性验证
                    object_list.append(new_object)
                except Exception as e:
                    formset.error[i].update(e)
                    generate_formset=formset
                    has_error=True
            if not has_error:
                Permission.objects.bulk_create(object_list,batch_size=100)
        else:
            generate_formset=formset

    #批量更新
    if request.method == "POST" and post_type == "update":
        formset = update_formset_class(data=request.POST)
        if formset.is_valid():
            post_row_list = formset.cleaned_data
            for i in range(0, formset.total_form_count()):
                row_dict = post_row_list[i]
                permission_id=row_dict.pop('id')
                try:
                    row_object = Permission.objects.filter(id=permission_id).first()
                    for k,v in row_dict.items():
                        setattr(row_object,k,v)
                    row_object.validate_unique()
                    row_object.save()
                except Exception as e:
                    formset.error[i].update(e)
                    update_formset = formset
        else:
            update_formset = formset

    #1.获取项目中所有的url
    url_dict=get_all_url_dict()
    # for name,url in url_dict.items():
    #     print(name,url)
    router_name_set=set(url_dict.keys())
    # print(router_name_set)
    #2.获取数据库中所有的url name
    permissions=Permission.objects.all().values('id','title','name','url','menu_id','pid_id')
    permission_dict=OrderedDict()
    permission_name_set=set()
    for row in permissions:
        permission_dict[row['name']]=row
        permission_name_set.add(row['name'])
    # print(permission_dict)
    # permission_name_set = set(permission_dict.keys())

    #把自动获取的router url和数据库中的做下对比，并更新数据库中的url值
    for name,value in permission_dict.items():
        router_row_dict=url_dict.get(name)
        if not router_row_dict:
            continue
        if value['url'] != router_row_dict['url']:
            value['url']='路由和数据库中的不一致'
        # print(permission_dict[name]['url'],router_row_dict['url'],value['url'] != router_row_dict['url'])

    #3.应该添加，删除修改的权限有那些
    if not generate_formset:
        generate_name_list=router_name_set-permission_name_set#add
        generate_formset=generate_formset_class(initial=[row_dict for name,row_dict in url_dict.items() if name in generate_name_list])

    delete_name_list=permission_name_set-router_name_set#delete
    delete_row_list=[row_dict for name,row_dict in permission_dict.items() if name in delete_name_list]
    # print(router_name_set)
    # print(permission_name_set)
    if not update_formset:
        update_name_list=permission_name_set & router_name_set#update
        # print(update_name_list)
        update_formset=update_formset_class(initial=[row_dict for name,row_dict in permission_dict.items() if name in update_name_list])
    # print(delete_row_list)
    # print(generate_name_list)
    # print(update_name_list)
    context = {
        'generate_formset':generate_formset,
        'delete_row_list':delete_row_list,
        'update_formset':update_formset,
    }
    return render(request, 'rbac/multi_permissions.html', context)


def multi_permissions_del(request,pk):
    origin_url = memory_reverse_url(request, 'rbac:multi_permissions')
    if request.method == "GET":
        return render(request, 'rbac/delete.html', {'cancel': origin_url})
    Permission.objects.filter(pk=pk).delete()
    return redirect(origin_url)


def distribute_permissions(request):
    """
    权限分配
    :param request:
    :return:
    """

    user_model_class=import_string(settings.RBAC_USER_MODEL_CLASS)
    # print(user_model_class)
    all_user_list=user_model_class.objects.all()
    all_role_list=Role.objects.all()
    menu_permissions_list=[]

    #temp vars
    user_id = None
    role_id = None
    user_has_roles=None
    user_has_roles_dict = {}
    user_has_permissions_dict = {}

    user_id=request.GET.get('uid')
    role_id = request.GET.get('rid')
    user_object=user_model_class.objects.filter(id=user_id).first()
    role_object=Role.objects.filter(id=role_id).first()


    if not user_object:
        user_id=None
    if not role_object:
        role_id=None

    if request.method == "POST" and request.POST.get("type") == "role":
        role_id_list = request.POST.getlist("roles")
        # 把用户和角色的关系进行保存，添加到第三张表
        # print(user_object,role_id_list)
        if not user_object:
            return HttpResponse('请选择用户')
        if user_object:
            user_object.roles.set(role_id_list)

    if request.method == "POST" and request.POST.get("type") == "permission":
        permission_id_list=request.POST.getlist("permissions")
        print(permission_id_list)
        if not role_object:
            return HttpResponse("请选择角色,然后再分配权限")
        if role_object:
            role_object.permissions.set(permission_id_list)

    if user_id:
        user_has_roles=user_object.roles.all()
        # print(user_has_roles)
    else:
        user_has_roles=[]

    user_has_roles_dict={ item.id:None for item in user_has_roles}
    """
    {
        1:None,2:None,3:None
    }
    
    """
    #获取当前用户所拥有的权限,如果选中了角色，优先显示选中角色所拥有的权限
    if role_object:#选择了角色
        user_has_permissions = role_object.permissions.all().distinct()
        user_has_permissions_dict = {item.id for item in user_has_permissions}
    elif user_id:#如果选择了用户
        user_has_permissions=user_object.roles.filter(permissions__isnull=False).values('id','permissions').distinct()
        user_has_permissions_dict = {item['permissions']: None for item in user_has_permissions}
        # print(user_has_permissions)
    else:
        user_has_permissions=[]
        user_has_permissions_dict ={}
    # print(user_has_permissions,"dd")


    # print(user_has_roles_dict)

    #所有的菜单（一级菜单）
    all_menu_list=Menu.objects.values('id','title')
    """
        [
            {id:1,title:一级菜单1,children:[{id:1,title:二级x1, menu_id:1,'children':[{id:11,title:权限x2,pid:1},] },{id:2,title:权限x1, menu_id:1 },]},
            {id:2,title:一级菜单2,children:[{id:3,title:二级x2, menu_id:2 },{id:5,title:x1, menu_id:2 },]},
            {id:3,title:一级菜单3,children:[{id:4,title:二级x2, menu_id:3 },]},
        ]
    """
    all_menu_dict={}
    #all_menu_list 与all_menu_dict中的字典内存地址相同，所以如果其中的内容修改后，都会进行修改
    """
       {
           1:{id:1,title:菜单1,children:[{id:1,title:x1, menu_id:1,children:[{id:11,title:x2,pid:1},] },{id:2,title:x1, menu_id:1,children:[] },]},
           2:{id:2,title:菜单2,children:[{id:3,title:x1, menu_id:2,children:[] },{id:5,title:x1, menu_id:2,children:[] },]},
           3:{id:3,title:菜单3,children:[{id:4,title:x1, menu_id:3,children:[] },]},
       }
   """
    for item in all_menu_list:
        item['children']=[]
        all_menu_dict[item['id']]=item
    # print(all_user_list)
    # print(all_role_list)
    #所有的二级菜单
    all_second_menu_list=Permission.objects.filter(menu__isnull=False).values('id','title','menu_id')
    """
    [
        {id:1,title:x1, menu_id:1,children:[{id:11,title:x2,pid:1},] },   
        {id:2,title:x1, menu_id:1,children:[] },
        {id:3,title:x1, menu_id:2,children:[] },
        {id:4,title:x1, menu_id:3,children:[] },
        {id:5,title:x1, menu_id:2,children:[] },
    ]
    """
    all_second_menu_dict={}
    """
    {
        1:{id:1,title:x1, menu_id:1,children:[{id:11,title:x2,pid:1},] },   
        2:{id:2,title:x1, menu_id:1,children:[] },
        3:{id:3,title:x1, menu_id:2,children:[] },
        4:{id:4,title:x1, menu_id:3,children:[] },
        5:{id:5,title:x1, menu_id:2,children:[] },
    }
    """
    for row in all_second_menu_list:
        row['children']=[]
        all_second_menu_dict[row['id']]=row
        menu_id=row['menu_id']
        all_menu_dict[menu_id]['children'].append(row)

    # 所有的三级菜单即权限,menu 为空者是三级菜单即权限
    all_permission_list = Permission.objects.filter(menu__isnull=True).values('id', 'title', 'pid_id')
    """
    [
        {id:11,title:x2,pid:1},
        {id:12,title:x2,pid:1},
        {id:13,title:x2,pid:2},
        {id:14,title:x2,pid:3},
        {id:15,title:x2,pid:4},
        {id:16,title:x2,pid:5},
    ]
    """
    for row in all_permission_list:
        pid=row['pid_id']
        if not pid:
            continue
        all_second_menu_dict[pid]['children'].append(row)
    #数据转换成字典后方便查找，hash查找比较快

    """
    [
        {
            id:1,
            title:'业务管理'
            children:[
                {
                    'id':11, 
                    title:'账单列表',
                    children:[
                        {'id':12,title:'添加账单'}
                    ]
                },
                {'id':11, title:'客户列表'},
            ]
        },

    ]
    """
    # print(all_menu_dict)
    context = {
        'user_list':all_user_list,
        'role_list':all_role_list,
        'all_menu_list':all_menu_list,
        'user_id':user_id,
        'role_id':role_id,
        'user_has_roles_dict':user_has_roles_dict,
        'user_has_permissions_dict':user_has_permissions_dict
    }

    return render(request,'rbac/distribute_permissions.html',context)